package com.cloudfun.campusshare.device.protocol.command;

import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.util.ByteUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * 波轮洗衣机
 * Created by Huqin on 2020/1/15
 */
public class BxyCommandFactory extends CommandFactory {

    public static final Map<Integer, String> washTypeMap = new HashMap<>();

    static {
        washTypeMap.put(1, "23");//1标准
        washTypeMap.put(2, "0F");//2快速
        washTypeMap.put(3, "11");//3大物
        washTypeMap.put(4, "1C");//4单脱
        washTypeMap.put(5, "0D");//5桶自洁
    }

//    /**
//     * 桶自洁
//     *
//     * @return
//     */
//    public Frame barrelSelfCleaning() {
//        return washGroupCommand(5, getAddFunc(false));
//    }
//
//    /**
//     * 单脱
//     *
//     * @return
//     */
//    public Frame onlySpin() {
//        return washGroupCommand(4, getAddFunc(false));
//    }
//
//    /**
//     * 快速
//     *
//     * @return
//     */
//    public Frame speedy() {
//        return washGroupCommand(2, getAddFunc(false));
//    }
//
//    /**
//     * 标准
//     *
//     * @return
//     */
//    public Frame normal() {
//        return washGroupCommand(1, getAddFunc(false));
//    }
//
//    /**
//     * 大物
//     *
//     * @return
//     */
//    public Frame heavy() {
//        return washGroupCommand(3, getAddFunc(false));
//    }
//
//    /**
//     * 标准 杀菌
//     *
//     * @return
//     */
//    public Frame normalAndDisinfect() {
//        return washGroupCommand(1, getAddFunc(true));
//    }
//
//    /**
//     * 大物杀菌
//     *
//     * @return
//     */
//    public Frame heavyAndDisinfect() {
//        return washGroupCommand(3, getAddFunc(true));
//    }

    protected Map<Integer, String> getWashTypeMap() {
        return washTypeMap;
    }

    /**
     * 组命令帧
     *
     * @param washType            洗衣程序
     * @param disinfect           消毒功能
     * @param pulseNum            脉冲个数
     * @param addLaundryDetergent 自动投液
     * @return
     */
    public Frame washGroupCommand(int washType, boolean disinfect, int pulseNum, boolean addLaundryDetergent) {
        return this.washGroupCommand(washType, getAddFunc(washType, disinfect, pulseNum, addLaundryDetergent));
    }

    /**
     * 组命令帧
     *
     * @param washType
     * @param addFunc
     * @return
     */
    public Frame washGroupCommand(int washType, byte[] addFunc) {
        if (!getWashTypeMap().containsKey(washType)) {
            throw new BusinessException(Code.PARAMETER_ERROR);
        }
        String washTypeCode = getWashTypeMap().get(washType);
        // 子命令类型
        byte[] subCommandType = new byte[]{0, 1};
        // 参数1 洗衣程序
        byte[] washTypeBytes = ByteUtil.hexStringToByte(washTypeCode);
        washTypeBytes = new byte[]{0, washTypeBytes[washTypeBytes.length - 1]};

        byte[] params = new byte[30];
        // 参数1 洗衣程序
        int position = 0;
        System.arraycopy(washTypeBytes, 0, params, position, washTypeBytes.length);
        position += washTypeBytes.length;
        // 参数2-3 预留
        position += 4;
        // 参数4
        System.arraycopy(addFunc, 0, params, position, addFunc.length);
        position += addFunc.length;
        // 参数5-15 预留
        return groupCommand(subCommandType, params);
    }

    /**
     * 附加功能
     *
     * @param washType            洗衣程序
     * @param disinfect           消毒功能
     * @param pulseNum            脉冲个数
     * @param addLaundryDetergent 自动投液
     * @return
     */
    public static byte[] getAddFunc(int washType, boolean disinfect, int pulseNum, boolean addLaundryDetergent) {
        byte res = 0;
        switch (pulseNum) {
            case 1:
                res |= 1;
                break;
            case 2:
                res |= 1 << 1;
                break;
            case 3:
                res |= 1 << 2;
                break;
            case 4:
                res |= 1 << 3;
                break;
        }
        switch (washType) {
            case 1:
                if (addLaundryDetergent) {
                    res |= 1 << 2;
                }
                break;
            case 2:
                if (addLaundryDetergent) {
                    res |= 1 << 1;
                }
                break;
            case 3:
                if (addLaundryDetergent) {
                    res |= 1 << 3;
                }
                break;
        }
        if (disinfect) {
            res |= 1 << 4;
        }
        return new byte[]{0, res};
    }
}
